import time

class Logics:
    def __init__(self):
        self.operator = None
        self.xs = None
        self.ys = None
        self.x2idx = {}
        self.y2idx = {}
        self.c2v = {}

    def set_operator(self, _operator):
        self.operator = _operator

    def check_all(self):
        for i in range(0, 10):
            for j in range(0, 16):
                for m in range(-9, 9):
                    for n in range(-15, 15):
                        self.check_neigbor(i, j, m, n)

    def start(self, data):
        # print("logics", data.keys())
        self.build_coords(data)

        for i in range(0, 10):
            for j in range(0, 16):
                self.check_neigbor(i, j, 1, 0)
                self.check_neigbor(i, j, -1, 0)
                self.check_neigbor(i, j, 0, 1)
                self.check_neigbor(i, j, 0, -1)

        for i in range(0, 10):
            for j in range(0, 16):
                self.check_neigbor(i, j, 2, 0)
                self.check_neigbor(i, j, -2, 0)
                self.check_neigbor(i, j, 0, 2)
                self.check_neigbor(i, j, 0, -2)

        for i in range(0, 10):
            for j in range(0, 16):
                self.check_neigbor(i, j, 1, 1)
                self.check_neigbor(i, j, 1, -1)
                self.check_neigbor(i, j, -1, 1)
                self.check_neigbor(i, j, -1, -1)

        for i in range(0, 10):
            for j in range(0, 16):
                self.check_neigbor(i, j, 3, 0)
                self.check_neigbor(i, j, -3, 0)
                self.check_neigbor(i, j, 0, 3)
                self.check_neigbor(i, j, 0, -3)

                self.check_neigbor(i, j, 4, 0)
                self.check_neigbor(i, j, -4, 0)
                self.check_neigbor(i, j, 0, 4)
                self.check_neigbor(i, j, 0, -4)

        for i in range(0, 10):
            for j in range(0, 16):
                self.check_neigbor(i, j, 1, 2)
                self.check_neigbor(i, j, 2, 1)
                self.check_neigbor(i, j, 1, -2)
                self.check_neigbor(i, j, -2, 1)
                self.check_neigbor(i, j, -1, 2)
                self.check_neigbor(i, j, 2, -1)
                self.check_neigbor(i, j, -1, -2)
                self.check_neigbor(i, j, -2, -1)

        for i in range(0, 10):
            self.check_all()

                # # check right:
                # rp = (i, j)
                # if i + 1 <= 9:
                #     cp = (i + 1, j)
                #     if self.c2v.get(rp, 0) + self.c2v.get(cp, 0) == 10:
                #         self.left_drag(rp, cp)
                #         self.c2v[rp] = 0
                #         self.c2v[cp] = 0

    def build_coords(self, data):
        raw_xs = {}
        raw_ys = {}
        for k, points in data.items():
            for p in points:
                # x = int(p[0])  # python 3.11 cv2
                # y = int(p[1])
                x = int(p[0][0])
                y = int(p[0][1])
                stx = self.contains_same(list(raw_xs.keys()), x, 3)
                stx = x if stx < 0 else stx
                sty = self.contains_same(list(raw_ys.keys()), y, 3)
                sty = y if sty < 0 else sty
                raw_xs[stx] = 1
                raw_ys[sty] = 1
                self.c2v[(stx, sty)] = k
        self.xs = list(raw_xs.keys())
        self.xs.sort()
        for idx, v in enumerate(self.xs):
            self.x2idx[v] = idx
        self.ys = list(raw_ys.keys())
        self.ys.sort()
        for idx, v in enumerate(self.ys):
            self.y2idx[v] = idx
        
        all_coords = list(self.c2v.keys())
        # print(len(all_coords), self.x2idx, self.y2idx)
        for coord in all_coords:
            i = self.x2idx.get(coord[0])
            j = self.y2idx.get(coord[1])
            self.c2v[(i, j)] = self.c2v[coord]
            self.c2v.pop(coord)
        # print(self.c2v)

    def contains_same(self, target_list, val, accuracy=0.1):
        for v in target_list:
            if self.is_same(v, val, accuracy):
                return v
        return -1

    def is_same(self, a, b, accuracy=0.1):
        if abs(a - b) < accuracy:
            return True
        return False


    def left_drag(self, coord1, coord2):
        start_x = self.xs[coord1[0]]
        start_y = self.ys[coord1[1]]
        end_x = self.xs[coord2[0]]
        end_y = self.ys[coord2[1]]
        self.operator.left_drag(start_x, start_y, end_x, end_y, 0.005)

    def check_neigbor(self, i, j, offx, offy):
        rp = (i, j)
        if self.c2v.get(rp, 0) == 0:
            return
        if i + offx > 9:
            return
        if i + offx < 0:
            return
        if j + offy > 15:
            return
        if j + offy < 0:
            return        

        start_row = min(i, i + offx)
        end_row = max(i, i + offx)
        start_col = min(j, j + offy)
        end_col = max(j, j + offy)
        
        sum = 0
        for r in range(start_row, end_row + 1):
            for c in range(start_col, end_col + 1):
                sum += self.c2v.get((r, c), 0)

        if sum == 10:
            self.left_drag(rp, (i + offx, j + offy))
            self.c2v[rp] = 0
            for r in range(start_row, end_row + 1):
                for c in range(start_col, end_col + 1):
                    self.c2v[(r, c)] = 0


